package cate.game.role.bag.hero;

import cate.common.table.d.GDBag;
import cate.common.table.d.GDObj;
import cate.common.table.item.hero.row.HeroBaseRow;
import cate.common.table.role.vip.RoleVipRow;
import cate.common.util.GameResult;
import cate.game.event.hero.HeroLevelChangeEvent;
import cate.game.event.hero.HeroStarChangeEvent;
import cate.game.res.MixRes;
import cate.game.res.MixResConsumer;
import cate.game.res.RewardShow;
import cate.game.role.Role;
import cate.game.role.bag.BagContainer;
import cate.game.role.bag.hero.msg.HeroAddResp;
import cate.game.role.bag.item.msg.ItemAddResp;
import cate.game.role.system.RoleSystem;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteField;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.annotation.Transient;

import java.util.Map;
import java.util.stream.Collectors;

/** 英雄背包 */
public class HeroBag extends BagContainer<Hero> {

    public HeroBag(){}

    public HeroBag(Role role) {
        super(role);
    }

    @Override
    protected byte getItemType() {
        return GDObj.Type.HERO;
    }

    @NoteField("英雄map")
    @JsonIgnore
    @Transient
    private transient Map<String ,Hero> map;

    @NoteField("已提交改变到统计服")
    public boolean changeCommittedStat;

    @NoteField("上次提交统计的时间")
    public long changeCommittedTime;

    @Override
    public void initialize(Role role){
        super.initialize(role);
        map = getList().stream().collect(Collectors.toMap(e->e.uid, e -> e));
    }

    @Override
    public int calcCapacity() {
        int tc = GDBag.Capcity.HERO + getExpandTimes() * GDBag.Expand.ADD_N;
        // vip额外加成格子
        RoleVipRow vipRow = role.getGame().table.vip.base.getByLevel(role.getBase().vip);
        if (vipRow != null) {
            tc += vipRow.heroBagExtraCapacity;
        }
        return tc;
    }

    @Override
    protected ItemAddResp<HeroAddResp> createItemAddMsg() {
        return new HeroAddResp();
    }

    @Override
    protected Hero createItem(int tid, long num) {
        return new Hero(role, tid);
    }

    @Override
    public HeroBaseRow getItemTpl(int templateId) {
        return role.getGame().table.hero.base.get(templateId);
    }

    @Override
    protected void onItemCreated(Hero e){
        super.onItemCreated(e);
        map.put(e.uid, e);
        HeroBaseRow tpl = getItemTpl(e.tid);
        publishEvent(role, new HeroLevelChangeEvent(role, e, 1));
        publishEvent(role, new HeroStarChangeEvent(role, e.uid, tpl.star, 0, tpl.camp));
        this.changeCommittedStat = false;

        if (tpl.star == 5) {
            if (tpl.quality < 4) {
                if (tpl.camp < 5) {
                    role.getSystem().update(RoleSystem.GmOper.LOWBI_FIVE_GET, 1);
                } else {
                    role.getSystem().update(RoleSystem.GmOper.LOWBI_FIVE_NIUBI_GET, 1);
                }
            } else {
                if (tpl.camp < 5) {
                    role.getSystem().update(RoleSystem.GmOper.NIUBI_FIVE_GET, 1);
                } else {
                    role.getSystem().update(RoleSystem.GmOper.NIUBI_FIVE_NIUBI_GET, 1);
                }
            }
        }
    }

    @Override
    public RewardShow onItemRemoved(Hero e){
        super.onItemRemoved(e);
        map.remove(e.uid);
        HeroBaseRow heroRow = e.getTpl(role.toPlayBuildContext());
        publishEvent(role, new HeroStarChangeEvent(role, e.uid, 0, heroRow.star, heroRow.camp));
        publishEvent(role, new HeroLevelChangeEvent(role, e, 0));
        this.changeCommittedStat = false;
        return null;
    }

    /** 根据_id获取指定对象 */
    @Override
    public Hero getItem(String uid) {
        if(StringUtils.isBlank(uid)){
            return null;
        }
        Hero hero = map.get(uid);
        if(hero == null){
            return super.getItem(uid);
        }
        return hero;
    }

    public void tick() {
        this.getRole().getGame().stat.heroPlus.tryReport(this);
    }

    public void markHeroChanged() {
        this.changeCommittedStat = false;
    }

    @Override
    public GameResult<Void> tryAddCapacity() {
        GameResult<Void> r = new GameResult<>();
        // 英雄背包特殊处理
        if (getExpandTimes() >= GDBag.Expand.HERO_BAG_EXPAND_MAX) {
            return r.fail("扩容次数到达上限");
        }
        // 每购买X次，消耗元宝会递增1次
        MixRes consume = new MixRes(GDBag.Expand.M1_OFFSET);
        consume.addList(new MixRes(GDBag.Expand.M1_COEF).multiply(getExpandTimes() / GDBag.Expand.BUY_N));
        return new MixResConsumer<Void>()
                .res(consume)
                .msg("扩容成功")
                .success(e -> {
            addCapacity();
            return null;
        }).exe(role);
    }

    public void createHeroFirst(Hero hero) {
        getList().add(hero);
        map.put(hero.uid, hero);
        role.getRes().heroIntroduction.addHero(hero.tid, hero.getTpl(role.getGame()).protoId);
    }
}
